package com.share.config.aop.decrypt;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.share.common.common.ReqParam;
import com.share.common.utils.AESUtil;
import com.share.common.utils.ClassUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;

import java.lang.reflect.Method;
import java.lang.reflect.Parameter;

@Slf4j
@Aspect
@Order(3)
@Component
public class DecryptRequestAspectImpl {

    //@Within表示匹配类上的指定注解，@annotation表示匹配方法上的指定注解
    @Pointcut("@within(com.share.config.aop.decrypt.DecryptRequest) || @annotation(com.share.config.aop.decrypt.DecryptRequest)")
    public void joinPointcut() {

    }

    /**
     * 调用数据源AOP处理
     *
     * @param joinPoint
     * @return
     * @throws Throwable
     */
    @Around("joinPointcut()")
    public Object round(ProceedingJoinPoint joinPoint) throws Throwable {
        Object[] newArgs = null;
        try {
            newArgs = calcNewParam(joinPoint);
        } catch (Exception e) {
            e.printStackTrace();
        }

        Object result = null;
        if (newArgs == null) {
            result = joinPoint.proceed();
        } else {
            result = joinPoint.proceed(newArgs);
        }
        return result;
    }

    private Object[] calcNewParam(ProceedingJoinPoint joinPoint) throws Exception {
        Method method = ((MethodSignature) joinPoint.getSignature()).getMethod();
        Parameter[] parameters = method.getParameters();
        Object[] args = joinPoint.getArgs();
        int paramSize = parameters.length;
        Object[] reArg = new Object[paramSize];
        for (int i = 0; i < paramSize; i++) {
            Object obj = args[i];
            if (obj != null && obj instanceof ReqParam) {
                //值存在,且类型正确
                ReqParam reqParam = (ReqParam) obj;
                if (StringUtils.isNotBlank(reqParam.getData())) {
                    //且非空
                    Parameter parameter = parameters[i];
                    obj = deCodeReqParam(parameter, reqParam);
                }
            }
            reArg[i] = obj;
        }
        return reArg;
    }

    private ReqParam deCodeReqParam(Parameter parameter, ReqParam req) throws Exception {
        String strJSON = AESUtil.decryptByDefaultKey(req.getData());
        Class<?>[] paramType = ClassUtil.getActualTypeArgument(parameter.getParameterizedType());
        req.setUncrypt(JSON.parseObject(strJSON, paramType[0]));
        return req;
    }

    public static void main(String[] args) {
        JSONObject obj = new JSONObject();
        obj.put("pageSize", 5);
        String s = null;
        try {
            s = AESUtil.encryptByDefaultKey(JSON.toJSONString(obj));
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
        System.out.println(s);
    }
}
